var fs = require('fs');
var config = require('../../../config.json');
var WorkspaceProxy = require('../../../proxy/workspace.js');
var ProjectProxy = require('../../../proxy/project.js');
var MemberProxy = require('../../../proxy/member.js');
var Workspace = require('../../../models/workspace.js');
var EventProxy = require('eventproxy');
var path = require('path');
var logger = require('log4js').getLogger();
var request = require('request');
var waterfall = require('async-waterfall');
var xml2js = require('xml2js');
var X2JPaser = new xml2js.Parser();
var builder = new xml2js.Builder();
var uuid = require('uuid');
var platform = require('os').platform();
var link = require('./target.js').link;
var cloneGitRepository = require('./gitoper.js').cloneGitRepository;
var createGitRepository = require('./gitoper.js').createGitRepository;
var dirs = require('./dirs.js').getDirs();
var removeDir = require('../../../common/removeDir.js');
//var getMaster = require('./gitoper.js').cloneGit;
var pullGit = require('./gitoper.js').pullGit;
var rmdirAllSync = require('../../../common/tools.js').rmdirAllSync;
var getTargetDirs = require('./dirs.js').getTargetDirs;
var workspace_dirs = require('./dirs.js').workspace_dirs;
var _ = require('lodash');
var child_process = require('child_process');
var execSync = child_process.execSync;
var copy = require('./target.js').copy;
var sdp_agent = config.server_agent.host + ":" + config.server_agent.port;
var messageAgent = require("../../../common/message.js");

/**
 * 新建工作空间
 * {workinfo:{
 *     work_name:工作空间名称
 *     project_id:项目id
 * }}
 * @param req
 * @param res
 * @param next
 */
exports.addWorkspace = function (req, res, next) {

    var task_id = uuid.v1();
    res.format_json({task_id: task_id}, 200);

    var work_name = req.body.work_name;
    var project_id = req.body.project_id;
    var work_info = {
        work_name: work_name,
        project_id: project_id,
        user: {
            "role": "creator",
            "name": req.body.userName,
            "shortId": req.body.userId
        }
    };

    waterfall([
        function (cb) {
            messageAgent.setMessage(task_id, {msg: "获取项目信息...", isCompleted: false, err: null});
            ProjectProxy.getProjectById(work_info.project_id, function (err, project) {
                if (err) {
                    logger.error(err);
                    messageAgent.setMessage(task_id, {msg: null, isCompleted: true, err: "获取项目信息失败"});
                    return false;
                }

                cb(null, project);
            });
        },
        function (project, cb) {
            messageAgent.setMessage(task_id, {msg: "创建工作空间信息...", isCompleted: false, err: null});
            work_info.dependencies = project.dependencies;
            WorkspaceProxy.addWorkspace(work_info, function (err, workspace) {
                if (err) {
                    logger.error(err);
                    messageAgent.setMessage(task_id, {msg: null, isCompleted: true, err: "创建工作空间信息失败"});
                    return false;
                }
                cb(null, project, workspace);
            });
        },
        function (project, workspace, cb) {
            messageAgent.setMessage(task_id, {msg: "创建工作空间目录...", isCompleted: false, err: null});
            var namespace_id = project.namespace + "$" + project.namespace + "$" + workspace.work_name
            request.post(sdp_agent + "/api/workspace/" + namespace_id,
                {
                    form: {
                        project_name: project.name,
                        namespace: project.namespace,
                        workspace_name: workspace.work_name
                    }
                }, function (err, response, data) {
                    var dataJson = JSON.parse(data);
                    if (dataJson.code == 200) {
                        if (dataJson.data.task_id) {
                            messageAgent.getMessage(sdp_agent + "/api/workspace/" + namespace_id + "?task_id=" + dataJson.data.task_id, function (msg) {
                                if (msg.err) {
                                    logger.error(msg.err);
                                    var task_err = msg.err;
                                    //agent创建工作空间目录失败，回滚数据
                                    request({
                                        url: sdp_agent + "/api/workspace/" + namespace_id,
                                        method: "DELETE",
                                        json: true,
                                        body: {
                                            project_name: project.name,
                                            namespace: project.namespace,
                                            work_name: workspace.work_name
                                        }
                                    }, function (err, response, data) {
                                        var dataJson = JSON.parse(data);
                                        if (dataJson.code == 200) {
                                            if (dataJson.data.task_id) {
                                                messageAgent.getMessage(sdp_agent + "/api/workspace/" + namespace_id + "?task_id=" + dataJson.data.task_id, function (msg) {
                                                    if (msg.err) {
                                                        logger.error(msg.err);
                                                        logger.error(msg.err + ": 数据回滚失败");
                                                        messageAgent.setMessage(task_id, {
                                                            msg: null,
                                                            isCompleted: true,
                                                            err: msg.err
                                                        });
                                                        return false;
                                                    } else {
                                                        WorkspaceProxy.deleteWorkspace(workspace._id, function (err) {
                                                            if (err) {
                                                                logger.error(err);
                                                                messageAgent.setMessage(task_id, {
                                                                    msg: null,
                                                                    isCompleted: true,
                                                                    err: task_err + ",数据回滚失败"
                                                                });
                                                                return false;
                                                            }
                                                            logger.info("删除数据库数据成功,数据回滚成功");
                                                            messageAgent.setMessage(task_id, {
                                                                msg: null,
                                                                isCompleted: true,
                                                                err: task_err + ",数据回滚成功"
                                                            });
                                                            return true;
                                                        });
                                                    }

                                                })
                                            }
                                        }
                                    });
                                } else {
                                    if (msg.isCompleted) {
                                        cb(null, namespace_id);
                                    }
                                    messageAgent.setMessage(task_id, {msg: msg.msg, isCompleted: false, err: null});
                                }

                            })
                        }
                    }
                });

        },
        function (namespace_id, cb) {
            //更新依赖
            //request({
            //    url: sdp_agent + "/api/workspace/" + namespace_id,
            //    method: "PUT",
            //    json: true,
            //    body: {}
            //}, function (err, response, data) {
            //    if (err) {
            //        logger.error(err);
            //        messageAgent.setMessage(task_id, {
            //            msg: null,
            //            isCompleted: false,
            //            err: "为工作空间创建依赖失败"
            //        });
            //    }
                cb(null)
            //});
        }
    ], function (err) {
        if (err) {
            logger.error(err);
            logger.error("create workspace error: unknown reason");
            messageAgent.setMessage(task_id, {msg: null, isCompleted: true, err: "创建工作空间失败"});
        } else {
            messageAgent.setMessage(task_id, {msg: "创建工作空间完成", isCompleted: true, err: null});
        }
    });
};

/**
 * 删除工作空间
 * {workspaceId：工作空间数据库主键}
 * @param req
 * @param res
 * @param next
 */
exports.deleteWorkspace = function (req, res, next) {
    var task_id = uuid.v1();
    messageAgent.setMessage(task_id, {msg: '删除工作空间目录...', isCompleted: false, err: null});
    res.format_json({task_id: task_id}, 200);

    var work_info = req.body;
    var workspace_id = work_info.work_id;

    waterfall([
        //1.获取工作空间信息
        function (cb) {
            WorkspaceProxy.getWorkspaceById(workspace_id, function (err, workspace) {
                if (err) {
                    logger.error(err);
                }
                logger.info("获取工作空间信息成功");
                work_info.work_name = workspace.work_name;
                cb(null);
            });
        },
        function (cb) {
            WorkspaceProxy.deleteWorkspace(workspace_id, function (err) {
                if (err) {
                    logger.error(err);
                    //return call_back(err);
                }
                logger.info("删除数据库数据成功");
                cb(null)
            });
        },
        function (cb) {
            request({
                url: sdp_agent + "/api/workspace/" + work_info.namespace + "$" + work_info.project_name + "$" + work_info.work_name,
                method: "DELETE",
                json: true,
                body: work_info
            }, function (err, response, data) {
                var dataJson = data.data;
                if (data.code == 200) {
                    if (dataJson.task_id) {
                        messageAgent.getMessage(sdp_agent + "/api/workspace/" + work_info.namespace + "$" + work_info.namespace + "$" + work_info.work_name + "?task_id=" + dataJson.task_id, function (msg) {
                            if (msg.err) {
                                logger.error(msg.err);
                                messageAgent.setMessage(task_id, {msg: null, isCompleted: true, err: msg.err});
                            } else {
                                messageAgent.setMessage(task_id, {msg: msg.msg, isCompleted: false, err: null});
                                if (msg.isCompleted) {
                                    cb(null);
                                }
                            }

                        })
                    }
                }
            });
        }
    ], function (err) {
        if (err) {
            logger.error(err);
            messageAgent.setMessage(task_id, {msg: null, isCompleted: true, err: "删除工作空间失败"});
        }
        messageAgent.setMessage(task_id, {msg: "删除工作空间完成", isCompleted: true, err: null});

    });
};

/**
 * 根据project_id获取所有工作空间数据库信息
 * {project_id：项目id}
 * @param req
 * @param res
 * @param next
 */
exports.getWorkspaces = function (req, res, next) {
    var project_id = req.params.project_id;
    WorkspaceProxy.getWorkspaces(project_id, function (err, data) {
        if (err) {
            logger.error(err);
            res.status(500);
            return res.format_json(null, 500, err);
        }
        res.send(data);
    });
};

exports.getWorkspaceById = function (req, res, next) {
    var work_id = req.params.workspace_id;
    WorkspaceProxy.getWorkspaceById(work_id, function (err, workspaces) {
        if (err) {
            logger.error(err);
            res.status(500);
            return res.format_json(null, 500, err);
        }
        return res.format_json(workspaces, 200, null);
    });
};

exports.getAllWorkspaces = function (req, res, next) {
    res.setHeader("Access-Control-Allow-Origin", "*");
    Workspace.find().populate('project_id').exec(function (err, works) {
        if (err) {
            logger.error(err);
            return res.format_json(null, 500, err);
        }
        res.format_json(works, 0);
    });
};

/**
 * 根据当前用户获取所有workspaces
 * @param req
 * @param res
 * @param next
 */
exports.getWorkspacesByUser = function (req, res, next) {
    res.setHeader("Access-Control-Allow-Origin", "*");//跨域请求时需要
    var user_name = req.query.user_name;
    var role = "all";
    var name = req.query.name;
    MemberProxy.getProjects(user_name, role, function (err, data) {
        if (err) {
            logger.error(err);
            return res.format_json(null, 500, err);
        }
        var ep = new EventProxy();
        var project_ids = [];
        ep.fail(function (err) {
            res.format_json(null, 500, err);
        });
        ep.after('projects_info_found', data.length, function () {
            var condition = {project_id: {$in: project_ids}};
            if (name) {
                condition.work_name = name;
            }
            Workspace.find(condition).populate('project_id').exec(function (err, works) {
                if (err) {
                    logger.error(err);
                    return res.format_json(null, 500, err);
                }
                res.format_json(works, 0);
            });
        });

        data.map(function (info) {
            project_ids.push(info.projectId);
            ep.emit('projects_info_found');
        });
    });
};

/**
 * 根据当前用户shortid获取所有workspaces
 * @param req
 * @param res
 * @param next
 */
exports.getWorkspacesByShortId = function (req, res, next) {
    res.setHeader("Access-Control-Allow-Origin", "*");//跨域请求时需要
    var shortId = req.query.short_id;
    //var role = "all";
    var name = req.query.name;

    var condition = {
        "user": {
            "$elemMatch": {"shortId": shortId}
        }
    };
    if (name) {
        var namespace = req.query.namespace;
        var project_name = req.query.project;
        condition.work_name = name;
    }
    Workspace.find(condition).populate('project_id').exec(function (err, workspaces) {
        if (name) {
            if (namespace && project_name) {
                _.remove(workspaces, function (workspace) {
                    return workspace.project_id.name != project_name || workspace.project_id.namespace != namespace
                });
                return res.format_json(workspaces, 0);
            }
            return res.format_json([], 400, "查询参数错误");
        }
        res.format_json(workspaces, 0);
    });
};

/**
 * 获取项目下所有工作空间中工程列表
 * @param req
 * @param res
 * @param next
 */
//1.根据_id获取项目信息
//2.创建依赖  （需要项目依赖）
//3.拉取master分支 到source下
//4.分析projects
var getAllProjectsInWkp = function (req, res, next) {
    var traverse = require('../../../traverse_dir.js');
    var platform = require('os').platform();
    var isWin = false;
    switch (platform) {
        case 'linux' :
        case 'darwin' :
            break;
        case 'win32' :
            isWin = true;
            break;
    }
    var ep = new EventProxy();
    var project_id = req.params.project_id;
    var project = {};
    ep.fail(function (err) {
        return res.format_json(null, 500, err);

    });
    ep.on("get_project_info", function (project) {
        //此时不创建target
        //init_target_for_master_wkp(project, isWin, function (err) {
        //    if (err) {
        //        return res.format_json(null, 500, err);
        //    } else {
        ep.emit("create_link_target");
        //    }
        //});
    });
    ep.on("create_link_target", function () {
        var project_name = project.name;
        var namespace_name = project.namespace;
        var master_repo_path = path.join(config.master_workspaces, namespace_name, project_name, "source", project_name);
        var simpleGit = require('simple-git')(master_repo_path);
        pullGit(master_repo_path, "origin", "develop", function (error) {
            if (error) {
                logger.error("合并分支失败");
                logger.error(error);
                return res.format_json(null, 500, "合并分支失败");
            } else {
                pullGit(master_repo_path, config.workspace.gitolite.repo_pre + namespace_name + '/' + project_name, 'master', function (err, data) {
                    if (err) {
                        return res.format_json(null, 500, err);

                    } else {

                        var projects = [];
                        traverse.traverse_dir(master_repo_path, projects);
                        var projects_info = [];
                        ep.after("get_project", projects.length, function () {
                            res.format_json({projects: projects_info}, 200, null);
                        });
                        projects.map(function (project) {
                            fs.readFile(project + path.sep + '.project', 'utf-8', function (err, data) {
                                if (err) {
                                    console.error("error " + JSON.stringify(err));
                                } else {
                                    xml2js.parseString(data, {explicitArray: false}, function (err, json) {
                                        if (err) {
                                            logger.error("error");
                                        } else {
                                            var natureIds = json.projectDescription.natures.nature;
                                            if (typeof (natureIds) == 'string') {
                                                natureIds = [natureIds];
                                            }
                                            projects_info.push({
                                                location: path.relative(config.master_workspaces, project),
                                                natureIds: natureIds,
                                                name: json.projectDescription.name
                                            });
                                            ep.emit("get_project");
                                        }
                                    });
                                }
                            });
                        });
                    }
                });
            }
        });
    });

    ProjectProxy.getProjectById(project_id, function (err, project_info) {
        if (err) {
            return callback(err);
        }
        project = project_info;
        //create_wkp_dirs(project);
        ep.emit("get_project_info", project);
    });


};
exports.getAllProjectsInWkp = getAllProjectsInWkp;
function create_wkp_dirs(project_info) {
    var root = config.temp_workspaces;
    var full_name = "workspace" + project_info.name;
    var full_path = path.join(path.join(root, full_name));
    try {
        fs.accessSync(full_path, fs.R_OK);
        rmdirAllSync(full_path);
        fs.mkdirSync(full_path);
        dirs.map(function (dir, i) {
            fs.mkdirSync(path.join(root, full_name, dir));
        });
    } catch (e) {
        fs.mkdirSync(full_path);
        dirs.map(function (dir, i) {
            fs.mkdirSync(path.join(root, full_name, dir));
        });
    }
}

function init_target_for_master_wkp(project, isWin, callback) {
    var full_name = "workspace" + project.name;
    var workspaces = config.master_workspaces;
    var target_root = path.join(workspaces, project.namespace, project.name, workspace_dirs.Target);
    var repo_path = config.local_repo_addr;

    //遍历依赖列表
    var dependencies = project.dependencies;
    _.remove(dependencies, function (n) {  //只对正常状态和有更新状态的依赖进行操作
        return n.status <= 1;
    });
    var fileArray = [];
    var epx = new EventProxy();
    epx.fail(callback);

    epx.after('push_file', dependencies.length, function () {
        fileArray.map(function (dependency) {
            var dirs = [];
            var core_java = config.workspace.goods_type.core_java;
            var core_node = config.workspace.goods_type.core_node;
            var mk = config.workspace.goods_type.MK;
            var nectar_plugin = "app_plugin";
            switch (dependency.type) {
                case core_java:
                    dirs.push({
                        src_path: path.join(repo_path, dependency.file_name, "bundles"),
                        target_path: path.join(target_root, "core", "java", "bundles")
                    });
                    break;
                case core_node:
                    dirs.push({
                        src_path: path.join(repo_path, dependency.file_name),
                        target_path: path.join(target_root, "core", "node")
                    });
                    break;
                case mk:
                    dirs.push({
                        src_path: path.join(repo_path, dependency.file_name, "backend", "dev"),
                        target_path: path.join(target_root, "backend", "dev")
                    });
                    dirs.push({
                        src_path: path.join(repo_path, dependency.file_name, "backend", "prod"),
                        target_path: path.join(target_root, "backend", "prod")
                    });
                    dirs.push({
                        src_path: path.join(repo_path, dependency.file_name, "products"),
                        target_path: path.join(target_root, "products")
                    });
                    break;
                case nectar_plugin:
                    dirs.push({
                        src_path: path.join(repo_path, dependency.file_name),
                        target_path: path.join(target_root, "nectar_plugin")
                    });
                    break;
            }

            dirs.map(function (dir) {
                var file_array = fs.readdirSync(dir.src_path);
                file_array.map(function (filename, i) {
                    var src = path.join(dir.src_path, filename);
                    var target = path.join(dir.target_path, filename);
                    fs.exists(target, function (exists) {
                        if (exists) {
                            logger.error("make symbolic link failed :" + target + " has existed!");
                            return callback("make symbolic link failed :" + target + " has existed!");
                        }
                    });
                    fs.exists(src, function (exists) {
                        if (exists) {
                            var stat = fs.statSync(src);
                            var cmdStr;
                            if (isWin) {
                                if (stat.isDirectory()) {
                                    cmdStr = 'mklink /j ' + target + ' ' + src;
                                } else {
                                    cmdStr = 'mklink ' + target + ' ' + src;
                                }
                                execSync(cmdStr);
                            }
                            else {
                                //if (stat.isDirectory()) {
                                cmdStr = 'ln -sfT ' + src + ' ' + target;
                                //}else{
                                //    cmdStr = 'ln -sfT ' + src + ' ' + target;
                                //}
                                execSync(cmdStr);
                            }
                        } else {
                            logger.error("make symbolic link for '" + src + "'failed: no such file!");
                            return callback("make symbolic link for '" + src + "'failed: no such file!");
                        }
                    });

                });
                logger.info('linking ' + dir.src_path + ' to ' + dir.target_path + ' completed!');
            });
        });
        callback(null);
    });
    //删除旧的依赖
    fs.exists(target_root, function (exists) {
        var target_dirs = getTargetDirs();
        epx.after('mkdir_target', target_dirs.length, function () {
            dependencies.map(function (dependency) {
                fileArray.push({
                    file_name: dependency.name + "_" +
                    dependency.goods_version, type: dependency.type
                });
                epx.emit('push_file');
            });
        });
        if (exists) {
            removeDir.remove(target_root, function (err) {
                if (err) {
                    return callback(err);
                }
                try {
                    target_dirs.map(function (dir) {
                        fs.mkdirSync(path.join(workspaces, project.namespace, project.name, dir));
                        epx.emit('mkdir_target');
                    });
                } catch (e) {
                    return callback(e);
                }

            });
        } else {
            try {
                target_dirs.map(function (dir) {
                    fs.mkdirSync(path.join(workspaces, project.namespace, project.name, dir));
                    epx.emit('mkdir_target');
                });
            } catch (e) {
                return callback(e);
            }
        }

    });
}
exports.init_target_for_master_wkp = init_target_for_master_wkp;

exports.getAllProjects = getAllProjects;
function getAllProjects(project_id, callback) {
    var platform = require('os').platform();
    var isWin = false;
    switch (platform) {
        case 'linux' :
        case 'darwin' :
            isWin = false;
            break;
        case 'win32' :
            isWin = true;
            break;
    }
    var epx = new EventProxy();
    var project = {};
    epx.fail(function (err) {
        callback(err);
    });
    epx.on("get_project_info", function (project) {
        init_target_for_master_wkp(project, isWin, function (err) {
            if (err) {
                callback(err);
            } else {
                epx.emit("create_link_target");
            }
        });
    });
    epx.on("create_link_target", function () {
        var project_name = project.name;
        var namespace = project.namespace;
        var master_repo_path = path.join(config.master_workspaces, namespace, project_name, "source", project_name);
        var simpleGit = require('simple-git')(master_repo_path);
        pullGit(master_repo_path, "origin", "develop", function (error) {
            if (error) {
                logger.error("合并分支失败");
                logger.error(error);
                callback("merge develop error")
            } else {
                pullGit(master_repo_path, config.workspace.gitolite.repo_pre + namespace + '/' + project_name, 'master', function (err, data) {
                    if (err) {
                        logger.error("pull master error");
                        callback("pull master error")
                    } else {
                        logger.info("projects ready");
                        callback(null, "projects ready");
                    }
                });
            }
        });
    });

    ProjectProxy.getProjectById(project_id, function (err, project_info) {
        if (err) {
            return callback(err);
        }
        project = project_info;
        epx.emit("get_project_info", project);
    });

}

function create_workspace_error_rollback(workspace_info, callback) {
    request.post(sdp_agent + "/workspace/delete", {form: work_info}, function (err, response, data) {
        var dataJson = JSON.parse(data);
        if (dataJson.code == 200) {
            if (dataJson.data.task_id) {
                //messageAgent.getMessage(sdp_agent + '/message/' + dataJson.data.task_id, function (msg) {
                //    if (msg.err) {
                //        logger.error(msg.err);
                //        messageAgent.setMessage(task_id, {msg: null, isCompleted: true, err: msg.err});
                //    } else {
                //        messageAgent.setMessage(task_id, {msg: msg.msg, isCompleted: false, err: null});
                //        if (msg.isCompleted) {
                //            cb(null);
                //        }
                //    }
                //
                //})
            }
        }
    });
}

